/*******************************************************************************************
Copyright (C) 2016 Mestrelab Research S.L. All rights reserved.

This file is part of the Mnova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*******************************************************************************************/

/*globals nmr, date2ISOString, mainWindow, serialization, settings, FileDialog, Dir, File, BinaryStream, Application, NMRPredictorParams, NMRSpectrum, MnUi, MessageBox, ProgressDialog, Str, TextStream,*/

/*jslint plusplus: true, continue: true, indent: 4*/

function Import1DCSVGeneric_Engine() {
	"use strict";
}

Import1DCSVGeneric_Engine.getCurrentDate =	function getCurrentDate(aISO) {
	"use strict";

	var date;

	date = date2ISOString(new Date());
	if (aISO !== undefined && aISO) {
		date = date.replace(/\:/g, ".");
	}

	return date;
};

Import1DCSVGeneric_Engine.createSpectrum = function createSpectrum(aSize, aNuc, aMhz, aPpm1, aPpm2, aLogFile, aPathCSVFile) {
	"use strict";

	var result, spectrum;

	result = {};

	//Create spectrum object
	spectrum = new NMRSpectrum({
		1: {nucleus: aNuc, frequency: aMhz, from_ppm: aPpm1, to_ppm: aPpm2, size: aSize},
		filename: aPathCSVFile,
		origin: 'CSV file',
		title: ''
	}
		);

	if (spectrum.uuid === undefined) {
		aLogFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The spectrum creation process has failed";
		result.logFile = aLogFile;
	} else {
		result.spectrum = spectrum;
	}

	return result;
};

Import1DCSVGeneric_Engine.getDataToWrite = function getDataToWrite(aSpec, aRow, aRowData, aLogFile, aPathCSVFile, aArrayOfPoints) {
	"use strict";

	var result, intensity;

	result = {};
	result.status = true;
	result.logFile = aLogFile;

	//Index check control
	if (aRow === undefined) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The index value is undefined";
		result.status = false;
	} else if (isNaN(aRow)) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The index value is not a number";
		result.status = false;
	} else if (aRow < 0) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: Attempt to write to negative index";
		result.status = false;
	} else if (aRow >= aSpec.count()) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: Attempt to write to beyond the limits";
		result.status = false;
	}

	//Intensity check control
	if (aRowData === undefined) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The intensity value for index " + aRow + " is undefined";
		result.status = false;
	} else if (isNaN(aRowData)) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The intensity value for index " + aRow + " is not a number";
		result.status = false;
	} else {
		intensity = Number(aRowData);
	}

	if (result.status) {
		aArrayOfPoints.push(intensity);
	}

	return result;
};

Import1DCSVGeneric_Engine.writeDataToSpectrum = function writeDataToSpectrum(aSpec, aArrayOfData, aPathCSVFile, aLogFile) {
	"use strict";

	var result;

	result = {};
	result.logFile = aLogFile;
	result.status = true;

	//Spectrum check control
	if (aSpec === undefined || !aSpec.isValid()) {
		result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: Attempt to write to a not valid spectrum";
		result.status = false;
	} else {
		if (!(aSpec.setReal("all", aArrayOfData))) {
			result.logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: There was a problem writing the data into the spectrum";
			result.status = false;
		}
	}

	return result;
};

Import1DCSVGeneric_Engine.processCSVFile = function processCSVFile(aPathCSVFile, aColumnNumber, aStartRowNumber, aLastRowNumber, aStartPPM, aEndPPM, aFrequency, aNucleus, aBlockSize, aToken, aHeader, aProgressBar) {
	"use strict";

	var file, line, inStream, totalLines, aux2TotalLines, lines, i, fields, startRow, failedRows, flagBlankWarning,
		failedValues, size, logFile, startDate, column, progressBar, error, maxSize, intensity, currentIndex, dataArray,
		bufferMaxLines, currentConvertLine, lastRow, totalppmLines, flagBlankLine, spectrumResult, firstBlankLine, auxIntensity,
		flagStopConvertingProcess, warning, spectrum, writeResult;

	logFile = "";
	error = false;
	warning = false;
	file = new File(aPathCSVFile);

	if (aHeader !== undefined && aHeader) {
		logFile += "Started on: " + this.getCurrentDate() + "\n";
		logFile += "Data Directory: " + file.absDirPath + "\n";
		logFile += "Column: " + aColumnNumber + "\n";
		logFile += "First Row: " + aStartRowNumber + "\n";
		if (aLastRowNumber !== -1) {
			logFile += "Last Row: " + aLastRowNumber + "\n";
		} else {
			logFile += "Last Row: unlimited\n";
		}

		logFile += "Start ppm: " + aStartPPM + "\n";
		logFile += "End ppm: " + aEndPPM + "\n";
		logFile += "Nucleus: " + aNucleus + "\n";
		logFile += "Frequency: " + aFrequency + " MHz \n";
	}

	//Check rows interval
	if (aLastRowNumber !== -1 && aLastRowNumber < aStartRowNumber) {
		error = true;
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The start CSV row must be greater than the last CSV row";
	}

	//Check file
	if (!file.open(File.ReadOnly)) {
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The file could not be opened";
	}

	//Init the process if we do not get critical errors
	if (!error) {

		//Maximum size in MB per file in order to save it at once
		//The performance of the script is closely related with this parameter
		maxSize = 25;
		size = file.size / 1000000;

		//For huge files define the number of lines will be buffered before write to disk
		bufferMaxLines = 10000;

		//Open progressBar dialog
		if (aProgressBar !== undefined && aProgressBar) {
			progressBar = new ProgressDialog();
			progressBar.minimum = 0;
			progressBar.maximum = 100;
			progressBar.value = 0;
			progressBar.visible = true;
			progressBar.labelText = "Reading file: " + Str.fileNameFromPath(aPathCSVFile);
		}

		//Count the number of lines
		totalLines = 0;
		totalppmLines = 0;
		flagBlankLine = false;
		flagBlankWarning = false;
		firstBlankLine = -1;
		dataArray = [];
		line = "";
		currentConvertLine = 0;
		column = aColumnNumber - 1;
		startRow = aStartRowNumber;
		inStream = new BinaryStream(file);
		lastRow = aLastRowNumber;

		while (!inStream.atEnd() && (progressBar === undefined || !progressBar.wasCanceled)) {

			//Split by new lines reading byte by byte
			line += inStream.readBytes(aBlockSize).toString();
			while (!inStream.atEnd() && line[line.length - 1] !== "\n" && (progressBar === undefined || !progressBar.wasCanceled)) {
				line += inStream.readBytes(1).toString();
			}

			if (line.indexOf("\n") === -1 && !inStream.atEnd()) {
				continue;
			} else {
				line = line.replace(/\r/g, "");
				lines = line.split("\n");
			}

			//Remove the blank space created on previous iteration
			if (!inStream.atEnd()) {
				if (lines[lines.length - 1] === "") {
					lines.pop();
				}
			}

			//Get ppm lines. We assume that there are no blank lines in the data column.
			//If we meet a blank line then the data is finished. Hence we bear in mind the previous lines
			for (i = 0; i < lines.length && (progressBar === undefined || !progressBar.wasCanceled); i++) {
				totalLines++;
				if (lines[i].trim() === "") {
					flagBlankLine = true;
					if (firstBlankLine === -1) {
						firstBlankLine = totalLines;
					}
				} else {
					if (flagBlankLine) {
						flagBlankWarning = true;
					} else {
						totalppmLines++;
					}
				}
			}

			//Prepare next iteration
			line = "";
			if (aProgressBar !== undefined && aProgressBar) {
				progressBar.value = ((inStream.pos / file.size) * 100) * 0.5;
			}
		}

		//Warning for a blank line issue and display the number of the total rows
		if (flagBlankWarning && (firstBlankLine !== 1)) {
			if (lastRow === -1 || (lastRow !== -1 && lastRow > firstBlankLine)) {
				logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: The line " + firstBlankLine + " is blank. All the lines below have been ignored";
				error = true;
			}
		}
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO] : The file has " + totalLines + " rows";

		//Get the expected rows by using the starting point defined by the user
		if (lastRow !== -1) {
			if (lastRow > totalLines) {
				logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [WARNING]: The number of the total rows [" + totalLines + "] is lower than the last row selected [" + lastRow + "]";
				lastRow = totalLines;
				warning = true;
			}
			if (lastRow >= firstBlankLine) {
				logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [WARNING]: The last row selected is below the blank line issue";
				lastRow = firstBlankLine - 1;
				warning = true;
			}
		} else {
			lastRow = totalppmLines;
		}
		aux2TotalLines = Math.abs(lastRow - startRow) + 1;

		if (aux2TotalLines > 0) {

			//Get current date
			startDate = this.getCurrentDate();

			//Initalize vars
			line = "";
			inStream.pos = 0;
			failedRows = 0;
			failedValues = 0;
			currentIndex = -1;
			flagStopConvertingProcess = false;
			if (aProgressBar !== undefined && aProgressBar) {
				progressBar.labelText = "Converting file: " + Str.fileNameFromPath(aPathCSVFile);
				progressBar.update();
			}

			//Read the file block by block by setting the pointer file to the beginning newly
			inStream = new BinaryStream(file);
			while (!inStream.atEnd() && (progressBar === undefined || !progressBar.wasCanceled) && !flagStopConvertingProcess) {

				//Split by new lines reading byte by byte
				line += inStream.readBytes(aBlockSize).toString();
				while (!inStream.atEnd() && line[line.length - 1] !== "\n" && (progressBar === undefined || !progressBar.wasCanceled) && !flagStopConvertingProcess) {
					line += inStream.readBytes(1).toString();
				}

				if (line.indexOf("\n") === -1 && !inStream.atEnd()) {
					continue;
				} else {
					line = line.replace(/\r/g, "");
					lines = line.split("\n");
				}

				//Remove the blank space created on previous iteration
				if (!inStream.atEnd()) {
					if (lines[lines.length - 1] === "") {
						lines.pop();
					}
				}

				//Process each line
				for (i = 0; i < lines.length && (progressBar === undefined || !progressBar.wasCanceled) && !flagStopConvertingProcess; i++) {

					line = lines[i];
					currentConvertLine++;

					//Check ending row or blank line in order to stop the process
					if (line.trim() === "") {
						flagStopConvertingProcess = true;
					} else if (currentConvertLine > lastRow) {
						flagStopConvertingProcess = true;
					} else {
						//Adapt to a generic way
						line = line.replace(/,/g, aToken);
						line = line.replace(/\t/g, aToken);
						line = line.replace(/\s/g, aToken);

						//Checking for starting moment
						if (startRow <= currentConvertLine) {
							if (aProgressBar !== undefined && aProgressBar) {
								progressBar.value = 50 + ((inStream.pos / file.size) * 100) * 0.5;
							}

							//Checking to start at the the specified starting point
							fields = line.split(aToken);
							currentIndex++;

							//Create spectrum on first pass
							if (startRow === currentConvertLine) {
								spectrumResult = this.createSpectrum(lastRow - startRow + 1, aNucleus, aFrequency, aStartPPM, aEndPPM, logFile, aPathCSVFile);
								if (spectrumResult.spectrum !== undefined && spectrumResult.spectrum.uuid !== undefined && spectrumResult.spectrum.isValid()) {
									spectrum = spectrumResult.spectrum;
									nmr.beginModification(spectrum);
								} else {
									error = true;
									logFile = spectrumResult.logFile;
									if (warning) {
										logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed with warnings and errors";
									} else {
										logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed with errors";
									}
									return [error, logFile];
								}
							}

							//Columns related errors
							if (fields.length - 1 < column) {
								failedRows++;
								logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR] [Row " + currentConvertLine + "]: The column number is greater than the selected column numbering";
							} else {

								//Get intensity for each point
								auxIntensity = fields[column];
								intensity = Number(auxIntensity);

								//Here the line should be added to the spectrum
								writeResult = this.getDataToWrite(spectrum, currentIndex, intensity, logFile, aPathCSVFile, dataArray);
								logFile = writeResult.logFile;
								if (!writeResult.status) {
									failedValues++;
								}
							}
						}
					}
				}
				line = "";
			}
		}

		if (dataArray.length > 0) {
			//Reverse the data if is needed. This gets much more performance that playing with pop() and unshift() methods
			if (aStartPPM < aEndPPM) {
				dataArray = dataArray.reverse();
			}

			//Insert all data into the spectrum in a single shot
			writeResult = this.writeDataToSpectrum(spectrum, dataArray, aPathCSVFile, logFile);
			if (!writeResult.status) {
				error = true;
			}
			logFile = writeResult.logFile;
		} else {
			logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [ERROR]: No data available to write in spectrum";
		}

		//Update spectrum and fix vertical axis
		nmr.endModification(spectrum);
		spectrum.fitToHeight();
		spectrum.update();
		mainWindow.activeDocument.update();

		if (failedRows > 0 || failedValues > 0) {
			error = true;
		}

		file.close();
	}

	if (error && !warning) {
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed with errors";
	} else if (!error && warning) {
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed with warnings";
	} else if (error && warning) {
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed with warnings and errors";
	} else {
		logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: File processed successfully";
	}

	if (aProgressBar !== undefined && aProgressBar) {
		if (progressBar.wasCanceled) {
			logFile += "\n[" + this.getCurrentDate() + "] [" + aPathCSVFile + "] [INFO]: Process cancelled by the user";
		}

		progressBar.value = 100;
		progressBar.visible = false;
	}

	return [error, logFile];
};

Import1DCSVGeneric_Engine.writeDataToFile = function writeDataToFile(aFilePath, aValue, aAppend) {
	"use strict";

	var file, stream;

	file = new File(aFilePath);
	if (file.exists && aAppend !== undefined && aAppend) {
		file.open(File.Append);
	} else {
		if (file.exists) {
			File.remove(aFilePath);
		}
		File.create(aFilePath);
		file.open(File.WriteOnly);
	}
	stream = new TextStream(file);
	stream.codec = "UTF-8";
	stream.write(aValue);
	stream.flush();
	file.close();
};

Import1DCSVGeneric_Engine.readFile = function readFile(aPath, aSize) {
	"use strict";

	var stream, data, file, all;

	file = new File(aPath);
	file.open(File.ReadOnly);
	stream = new BinaryStream(file);
	data = stream.readBytes(aSize);
	all = stream.atEnd();
	file.close();

	return [data.toString(), all];
};

function import1DCSVGeneric() {
	"use strict";

	var fileName, fileNames, openDir, isPpm1StartingPoint, dialog, showDialog, block, columnNumber, i,
		showBar, logFilePath, useHeader, token, startRowNumber, lastRowNumber, statusLastRow, startPPM,
		endPPM, nucleus, frequency, lastDir, displayLog, logFile,
		dirSetKey = "Import 1D CSV Generic/Last Directory",
		columnNumberKey = "Import 1D CSV Generic/Column Number",
		startRowNumberKey = "Import 1D CSV Generic/First Row Number",
		lastRowNumberKey = "Import 1D CSV Generic/Last Row Number",
		lastRowStatusKey = "Import 1D CSV Generic/Last Row Status",
		ppm1RangeKey = "Import 1D CSV Generic/ppm1 Range",
		ppm2RangeKey = "Import 1D CSV Generic/ppm2 Range",
		frequencyKey = "Import 1D CSV Generic/Frequency",
		nucleusKey = "Import 1D CSV Generic/Nucleus",
		logFilePathKey = "Import 1D CSV Generic/File Path Log File",
		showLogKey = "Import 1D CSV Generic/Show Log";

	function padNumber(aNumber, aWidth, aPaddingSymbol) {

		var number, result;

		aPaddingSymbol = aPaddingSymbol || '0';
		number = String(aNumber);
		if (number.length >= aWidth) {
			result =  number;
		} else {
			result = [];
			result.length = aWidth - number.length + 1;
			result = result.join(aPaddingSymbol) + number;
		}

		return result;
	}

	function printPreviewData(aOnlyFirstAndLast, aData, aAllFile) {

		var richTextNumbering, richTextData, data, numberingLength, result;

		richTextNumbering = "<font style=\"font-size: 8pt; font-family: 'Arial'; color: Red\">";
		richTextData = "<font style=\"font-size: 8pt; font-family: 'Arial'; color: Black\">";
		result = "";
		data = aData.toString().split("\n");
		numberingLength = data.length.toString().length;
		if (aOnlyFirstAndLast) {
			result += richTextNumbering + padNumber(1, numberingLength) + ".&nbsp;&nbsp;</font>";
			result += richTextData + data[0].replace(/\n/g, "") + "</font><br>";
			result += richTextData + "[........]" + "</font><br>";
			result += richTextNumbering + padNumber(data.length, numberingLength) + ".&nbsp;&nbsp;</font>";
			result += richTextData + data[data.length - 1].replace(/\n/g, "") + "</font>";
		} else {
			for (i = 0; i < data.length; i++) {
				result += richTextNumbering + padNumber((i + 1), numberingLength) + ".&nbsp;&nbsp;</font>";
				result += richTextData + data[i] + "</font><br>";
			}
		}
		if (!aAllFile) {
			result += richTextData + "[........]" + "</font><br>";
		}

		return result;
	}

	function getPreviewData(aPath, aSize) {

		var i, result, data, all;

		//Retrive the last complete line
		result = Import1DCSVGeneric_Engine.readFile(aPath, aSize);
		data = result[0].toString();
		all = result[1];
		for (i = data.length - 1; !all && 0 <= i; i--) {
			if (data[i] === "\n") {
				data = data.substring(0, i);
				break;
			}
		}

		return [data, all];
	}

	function previewFile() {

		var dialog, showDialog, data, size, progressBar, result,
			sizePreviewKey = "Import 1D CSV Generic/Size Preview";

		dialog = Application.loadUiFile('ricares:import1DCSVFileViewer.ui');
		dialog.show();

		//Signal management
		dialog.widgets.tbReloadPreview.clicked.connect(dialog, function () {

			var size, result, progressBar;

			//Get default preview data
			size = 1024 * dialog.widgets.spbxSize.value;
			if (dialog.widgets.spbxSize.value > 50) {
				progressBar = new ProgressDialog();
				progressBar.visible = true;
				progressBar.labelText = "Previewing file: " + Str.fileNameFromPath(fileNames[0]);
			}
			result = getPreviewData(fileNames[0], size);
			data = printPreviewData(false, result[0].toString(), result[1]);
			dialog.widgets.tePreviewData.html = data;
			if (progressBar !== undefined) {
				progressBar.visible = false;
			}
		});

		//Load Settings
		dialog.widgets.spbxSize.value =  settings.value(sizePreviewKey, 100);

		//Get default preview data
		size = 1024 * dialog.widgets.spbxSize.value;
		if (dialog.widgets.spbxSize.value > 50) {
			progressBar = new ProgressDialog();
			progressBar.visible = true;
			progressBar.labelText = "Previewing file: " + Str.fileNameFromPath(fileNames[0]);
		}
		result = getPreviewData(fileNames[0], size);
		data = printPreviewData(false, result[0].toString(), result[1]);
		dialog.widgets.tePreviewData.html = data;
		if (progressBar !== undefined) {
			progressBar.visible = false;
		}

		//Execute preview dialog
		showDialog = true;
		while (showDialog) {

			//Check if cancle button is pulsed by user
			if (!dialog.exec()) {
				return;
			}
			showDialog = false;
		}

		//Save settings
		settings.setValue(sizePreviewKey, dialog.widgets.spbxSize.value);
	}

	//Get files by sorting alphabetically
	openDir = settings.value(dirSetKey, Dir.home());
	fileNames = FileDialog.getOpenFileNames("CSV Files(*.csv *.txt)", "", openDir);
	fileNames.sort(Dir.numericPathsCompare);

	//Configuration section
	block = 100;
	token = ";";
	showBar = true;

	//Cecking at least for one file
	if (!fileNames.length) {
		return;
	}

	//Load GUI
	lastDir = new File(fileNames[0]).absDirPath;
	dialog = Application.loadUiFile('ricares:import1DCSVGeneric.ui');
	dialog.show();
	logFilePath = Dir.temp();
	logFilePath = logFilePath.replace(/\\/g, "/");
	if (logFilePath[logFilePath.length - 1] !== "/") {
		logFilePath += "/";
	}

	//----------------SIGNALS MANAGEMENT---------------------
	dialog.widgets.tbRangeDirection.clicked.connect(dialog, function () {

		var aux;

		aux = dialog.widgets.spbxppm1.value;
		dialog.widgets.spbxppm1.value = dialog.widgets.spbxppm2.value;
		dialog.widgets.spbxppm2.value = aux;
	});

	dialog.widgets.tbLog.clicked.connect(dialog, function () {
		var filename;
		filename = dialog.widgets.leLog.text;
		filename = FileDialog.getSaveFileName("*.log", "Choose file", filename, 4);
		dialog.widgets.leLog.text = filename;
	});

	dialog.widgets.tbFilePreview.clicked.connect(previewFile);

	//Load registry values
	isPpm1StartingPoint = true;
	dialog.widgets.spbxStartCSVColumn.value = settings.value(columnNumberKey, 1);
	dialog.widgets.spbxStartCSVRow.value = settings.value(startRowNumberKey, 1);
	dialog.widgets.spbxLastCSVRow.value = settings.value(lastRowNumberKey, 16384);
	dialog.widgets.cbLastRow.checked = settings.value(lastRowStatusKey, false);
	dialog.widgets.spbxppm1.value = settings.value(ppm1RangeKey, 0);
	dialog.widgets.spbxppm2.value = settings.value(ppm2RangeKey, 0);
	dialog.widgets.leNucleus.text = settings.value(nucleusKey, "");
	dialog.widgets.spbxFrequency.value = settings.value(frequencyKey, 100);
	dialog.widgets.leLog.text = settings.value(logFilePathKey, logFilePath + "import1DCSVGeneric.log");
	dialog.widgets.cbShowLog.checked =  settings.value(showLogKey, true);

	//Execute dialog
	showDialog = true;
	while (showDialog) {

		//Check if cancle button is pulsed by user
		if (!dialog.exec()) {
			return;
		}

		if (dialog.widgets.cbLastRow.checked) {
			if (dialog.widgets.spbxStartCSVRow.value > dialog.widgets.spbxLastCSVRow.value) {
				MessageBox.warning("The start CSV row must be greater than the last CSV row.");
				continue;
			}
		}

		if (dialog.widgets.spbxppm1.value === dialog.widgets.spbxppm2.value) {
			MessageBox.warning("Wrong ppm range. The intervals must not be equal.");
			continue;
		}

		if (dialog.widgets.leLog.text === "") {
			MessageBox.warning("You must set a valid log file path.");
			continue;
		} else if (!(new Dir(new File(dialog.widgets.leLog.text).absDirPath).exists)) {
			MessageBox.warning("The absolute directory of the log file path does not exist.");
			continue;
		}

		showDialog = false;
	}

	//Get parameter values from GUI
	columnNumber = dialog.widgets.spbxStartCSVColumn.value;
	startRowNumber = dialog.widgets.spbxStartCSVRow.value;
	lastRowNumber = dialog.widgets.spbxLastCSVRow.value;
	frequency = dialog.widgets.spbxFrequency.value;
	nucleus = dialog.widgets.leNucleus.text;
	startPPM = dialog.widgets.spbxppm1.value;
	endPPM = dialog.widgets.spbxppm2.value;
	displayLog = dialog.widgets.cbShowLog.checked;
	logFilePath = dialog.widgets.leLog.text;
	statusLastRow = dialog.widgets.cbLastRow.checked;
	if (!statusLastRow) {
		lastRowNumber = -1;
	}

	//Save settings to the registry
	settings.setValue(dirSetKey, lastDir);
	settings.setValue(columnNumberKey, dialog.widgets.spbxStartCSVColumn.value);
	settings.setValue(startRowNumberKey, dialog.widgets.spbxStartCSVRow.value);
	settings.setValue(lastRowNumberKey, dialog.widgets.spbxLastCSVRow.value);
	settings.setValue(lastRowStatusKey, dialog.widgets.cbLastRow.checked);
	settings.setValue(ppm1RangeKey, dialog.widgets.spbxppm1.value);
	settings.setValue(ppm2RangeKey, dialog.widgets.spbxppm2.value);
	settings.setValue(frequencyKey, dialog.widgets.spbxFrequency.value);
	settings.setValue(nucleusKey, dialog.widgets.leNucleus.text);
	settings.setValue(logFilePathKey + "import1DCSVGeneric.log", dialog.widgets.leLog.text);
	settings.setValue(showLogKey, dialog.widgets.cbShowLog.checked);

	//Iterate trough the already sorted files
	serialization.fileHistory = false;
	for (i = 0; i < fileNames.length; i++) {
		fileName = fileNames[i];

		//Call to engine
		if (i === 0) {
			useHeader = true;
			logFile = "";
		} else {
			useHeader = false;
		}

		//Process file and get the log file
		logFile = Import1DCSVGeneric_Engine.processCSVFile(fileName, columnNumber, startRowNumber, lastRowNumber, startPPM, endPPM, frequency, nucleus, block, token, useHeader, showBar);

		if (Application.mainWindow.activeDocument !== undefined) {
			Application.mainWindow.activeDocument.update();
		}
		serialization.fileHistory = true;
	}

	//Log file management
	Import1DCSVGeneric_Engine.writeDataToFile(logFilePath, logFile, false);
	if (displayLog) {
		dialog = Application.loadUiFile('ricares:import1DCSVGenericDialogInspection.ui');
		dialog.show();
		dialog.widgets.teLog.plainText = logFile;
	}
}

if (this.MnUi && MnUi.scripts_nmr) {
	MnUi.scripts_nmr.scripts_nmr_Import1DCSVGeneric = import1DCSVGeneric;
}
